package de.jmda.core.util.jpa;

import javax.lang.model.element.ElementKind;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;

import de.jmda.core.mproc.ProcessingUtilities;

/**
 * Abstract base class for classes that provide information about entity
 * relations that {@link
 * EntityRelationInfoFactory#getEntityRelationInfo(VariableElement)} derives
 * from a single declaredField declaration (see
 * {@link EntityRelationInfo#declaredField}).
 */
public abstract class EntityRelationInfo
{
	/**
	 * allows fast detection of entity relation type without using <code>
	 * instanceof</code> reflection
	 */
	protected EntityRelation entityRelation;

	/**
	 * stores the declaredField from which {@link
	 * EntityRelationInfoFactory#getEntityRelationInfo(VariableElement)} derived
	 * this entity relation info
	 */
	protected VariableElement declaredField;

	/**
	 * stores <code>entityRelation</code> to {@link #entityRelation} and
	 * <code>declaredField</code> to {@link #declaredField}
	 *
	 * @param entityRelation
	 * @param variableElement
	 */
	protected EntityRelationInfo(
			EntityRelation entityRelation, VariableElement variableElement)
	{
		super();

		if (variableElement.getKind() != ElementKind.FIELD)
		{
			throw new IllegalArgumentException("variable element has to be a field");
		}

		this.entityRelation = entityRelation;
		declaredField = variableElement;
	}

	public EntityRelation getEntityRelation()
	{
		return entityRelation;
	}

	public VariableElement getField()
	{
		return declaredField;
	}

	public DeclaredType getDeclaringType()
	{
		return
				ProcessingUtilities.asDeclaredType(
						declaredField.getEnclosingElement().asType());
	}

	/**
	 * According to JSR-220 (EJB 3.0 specification) JPA, chapter 2.1.7 every
	 * entity relation has an owning side.
	 *
	 * @return field declaration of the owning declaredField in an entity relation
	 */
	public abstract VariableElement getOwningField();

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return
				"---" + EntityRelationInfo.class.getName() + " subtype: [" + getClass().getName() + "]\n" +
				"entity relation type [" + entityRelation + "]\n" +
				"declared declaredField [" + getDeclaringType() + "." + declaredField.getSimpleName() + "]";
	}
}